package com.sentiment.algorithm;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;



public class LshCorePage {

	/*
     * 以下key，signatureLength为二个参数
     * 二个参数均需要不断调试，以获得最佳数值
     * key：  k-shingle的k值大小 ，请取值为3到一句话的平均长度的3/4进行调试
     * signatureLength：签名长度，根据实际情况取值，如果是一篇文章，值可能需要比较大，但是不要超过80
     */
    private int key=7;
    private int signatureLength=80;
    /*
     * threadhold:参数 输出为0-100的整数，代表百分比，例如输入11，则为11%
     */
    
    private int threadhold=11;

    /*
     * 以下参数自动获得，保留
     */
    
    private int keyContinue;         //桶的大小
    private String articShing;       //临时文件名
    private int numberOfText;        //文章数目
    private String[] artics;         //输入的文件，待比较
    private String pattern;          //输入的需要查从文件
    private Matrix signNatureMap;    //签名矩阵
    private String simi="";          //相似度字符串
    private ArrayList<ArrayList<Integer>>  pageShingling = new
              ArrayList<ArrayList<Integer>>();         //k-shingle后每篇文章对应的桶值

    private HashMap<Integer,String> bucket = new HashMap<Integer, String>();   //桶
    private HashMap<String,Integer> store = new HashMap<String, Integer>();    

    private ArrayList<String> textStructrue=new ArrayList<String>();
    
    private String setFilename(String name){
		if(name.contains(".txt"))
			return name;
		else
			return name+".txt";
	}
    
    public static void main(String[] args){
        LshCorePage lsh=new LshCorePage();
        lsh.launchLsh("");
        
    }
    //启动lsh
    public void launchLsh(String name){
    	name = setFilename(name);
        SelfFile selfFile=new SelfFile();
        
        
//        ArgumentConf.articlesFilePath="C:\\Users\\asus\\workspace\\Detection1.1\\resultFiles";
//        ArgumentConf.PATTERNPATH="C:\\Users\\asus\\workspace\\Detection1.1\\srcTxtFiles\\分布式网络爬虫.txt";
//        ArgumentConf.similaroutputPath="C:\\Users\\asus\\workspace\\Detection1.1\\output\\009006.txt";
//        ArgumentConf.ARTICLESHING="C:\\Users\\asus\\workspace\\Detection1.1\\0007";
        
//        artics= selfFile.ShowDirListPath(ArgumentConf.articlesFilePath);
//        numberOfText=artics.length+1;
//        pattern=ArgumentConf.PATTERNPATH+name;
//        articShing=ArgumentConf.ARTICLESHING;
//        createTable();
//        minHash();
//        handleLsh();
//        writeToFileSimi(ArgumentConf.similaroutputPath);
//        System.out.println(keyContinue);
    }
    
    
    /*
     * 输出文章的相似比例
     */
    public void writeToFileSimi(String path){
        try{
            PrintWriter output=new PrintWriter(new BufferedWriter
                      (new FileWriter(path)));

            
            output.println(simi);

            output.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    
    
    /*
     * 根据文章的特性，简化的Lsh操作
     * numberOfText：文章数目
     * 直接计算出相似度，低于阙值不输出
     */
    
    public void handleLsh(){
        

        for(int i=0;i<numberOfText-1;i++){
        	int k=0;
            for(int j=0;j<signatureLength;j++){
            	if(signNatureMap.getNumberWithLineAndRow(i, j)==
            			signNatureMap.getNumberWithLineAndRow(numberOfText-1,j)){
            			k++;
            	}
            }
            double si=(double)k/(double)signatureLength;
            si=si*100;
            if(si>(double)threadhold){
            	StringBuilder strb=new StringBuilder();
                strb.append("0"+"\t"+"0"+"\t");
                String temp_f=artics[i].split("/")[artics[i].split("/").length-1];

                strb.append(temp_f+"\t"+"0"+"\t"+"0"+"\t");
                String mi=(int)si+"%";
                
                strb.append(mi);
                strb.append("\n");
                simi+=strb.toString();
            }
            
        }

    }
    
    /*
     * 建表过程，针对所有文章建表
     */
    public void createTable(){
        int i;
        for(i=0;i<artics.length;i++){
            createTableSin(artics[i],i);
        }
        createTableSin(pattern,i);
    }
    
    /*
     * 对每篇文章分句的预处理
     */
    public String getSentences(String str){
        return str.replaceAll("[.!;?。！；？]","-");
    }
    
    
    /*
     * 建表过程，针对所每篇文章建表
     */
    public void createTableSin(String fileName,int i){
    	
        ArrayList<Integer> arrayList=new ArrayList<Integer>();
        String structure="";
        String temp_f=fileName.split("/")[fileName.split("/").length-1];
        String regex="^[\\u0020\\u3000]*$";
        SelfFile selfFile=new SelfFile(fileName);
        String text_buffer="";
        int tureC=0;
        while(selfFile.getpatternPara()){


            String text=selfFile.getText().replaceAll(regex,"");
            if(text.trim().isEmpty()||"".equals(text.trim())){
                continue;
            }

            String[] sens=getSentences(text).split("-");

            int senLength=sens.length;
            structure+=tureC+":"+senLength+" ";
            tureC++;


            String shingstr;
            String para="";
            for(int j=0;j<senLength;j++){

                String s=sens[j];
                int remain=s.length();
                int point=0;
                int count=0;
                shingstr="";
                String buffer="";
                while(remain>=key){
                    remain--;
                    shingstr=shingstr+s.charAt(point);
                    count++;

                    if (count==key){
                        if(!store.containsKey(shingstr)){
                            bucket.put(keyContinue,shingstr);
                            store.put(shingstr,keyContinue);
                            buffer=buffer+keyContinue+" ";
                            keyContinue++;

                        }else {
                            buffer=buffer+store.get(shingstr)+" ";
                        }
                        arrayList.add(store.get(shingstr));
                        count=0;
                        shingstr="";
                        point=point-key+1;
                        remain=remain+key-1;
                    }
                    point++;
                }
                if(remain==(key-1)&&point!=0){

                    for(int k=0;k<key-1;k++){
                        char ch=s.charAt(point+k);
                        shingstr=shingstr+ch;
                    }
                    if(shingstr!=""){
                        if(!store.containsKey(shingstr)){
                            bucket.put(keyContinue,shingstr);
                            store.put(shingstr,keyContinue);
                            buffer=buffer+keyContinue+" ";
                            keyContinue++;
                        }else {
                            buffer=buffer+store.get(shingstr)+" ";
                        }
                        arrayList.add(store.get(shingstr));
                    }

                }
                para=para+buffer+".";
            }
            text_buffer=text_buffer+para+"\n";
        }
        textStructrue.add(structure);
        pageShingling.add(arrayList);
        try{
            PrintWriter output=new PrintWriter(new BufferedWriter
                      (new FileWriter(articShing+"//"+i+"_"+i)));

            output.println(text_buffer);

            output.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    
    
    /*
     * 初始化签名矩阵，设置值为最大Integer
     */
    
    public void setupSignature(){
        signNatureMap=new Matrix(numberOfText,signatureLength);
        for(int i=0;i<numberOfText;i++){
            for (int j=0;j<signatureLength;j++){
                signNatureMap.setNumberWithRowAndCol(i,j,Integer.MAX_VALUE);
            }
        }
    }
    
    
    /*
     * hashFuction过程，由hash函数组决定
     */
    public int hashFuction(int primePoint,int number){
//      System.out.print(PrimeNumber.number[primePoint]+"*");
      return (PrimeNumber.number[primePoint]*number+1)%keyContinue;
  }

    /*
     * 判断是否为有效的素数
     */
  public boolean isRightPrime(int primePoint){
      if((keyContinue%PrimeNumber.number[primePoint])==0){
          return false;
      }
      return true;
  }
    
  /*
   * 最小签名矩阵计算，初始化函数组合计算最小签名，获得一个最小签名的集合
   */
    public void minHash(){
        setupSignature();
        int primePoint=0;
        int [] indexOfPrime= new int[signatureLength];
        for(int i=0;i<signatureLength;primePoint++){
            if(isRightPrime(primePoint)){
                indexOfPrime[i]=primePoint;
//                System.out.print(primePoint + ",");
                i++;
            }
        }

        for(int i=0;i<numberOfText;i++){
            ArrayList<Integer> arrayList=pageShingling.get(i);
            for(Integer tem:arrayList){
                for(int j=0;j<signatureLength;j++){
                    int tempPrime=hashFuction(indexOfPrime[j],tem);
                    if(signNatureMap.getNumberWithLineAndRow(i,j)>tempPrime){
                        signNatureMap.setNumberWithRowAndCol(i,j,tempPrime);
                    }
                }
            }
        }

    }
    
}
